﻿using System;
using ESRI.ArcGIS;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;

namespace DllShepherd.ArcObjects.Introduction
{
    /// <summary>
    /// This code is meant to be as ugly as sin!
    /// It is an introduction to things to come and should NOT be used in ANY production code.
    /// The point is to show how example code from ESRI could be used - but shouldn't be used! 
    /// (once upon a time my current company used code such as this - that was the first thing I refactored)
    /// </summary>
    public class ShepherdBL
    {
        private object _missing = Type.Missing;
        public string SdeConnectionString { get; set; }

        public void UpdateSheepTrack(int code, IPoint location)
        {
            InitializeLicense();


            IWorkspaceFactory2 workspaceFactory = new SdeWorkspaceFactoryClass();
            var workspace = (IFeatureWorkspace)workspaceFactory.OpenFromString(SdeConnectionString, 0);

            UpdateTrack(code, location, workspace);
            UpdateLocation(code, location, workspace);
            AddHistoryLocation(code, location, workspace);
        }

        private void AddHistoryLocation(int code, IPoint location, IFeatureWorkspace workspace)
        {
            var featureClass = workspace.OpenFeatureClass("SHEEP_HISTORY_LOCATIONS");
            IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();

            using (var comReleaser = new ComReleaser())
            {
                IFeatureCursor featureCursor = featureClass.Insert(false);
                comReleaser.ManageLifetime(featureCursor);
                featureBuffer.Shape = location;
                featureBuffer.set_Value(featureBuffer.Fields.FindField("Code"), code);
                featureBuffer.set_Value(featureBuffer.Fields.FindField("ReportTime"), DateTime.Now);
                featureCursor.InsertFeature(featureBuffer);
                featureCursor.Flush();
            }
        }

        private void UpdateLocation(int code, IPoint location, IFeatureWorkspace workspace)
        {
            var filter = new QueryFilter { WhereClause = " Code = " + code };
            var featureClass = workspace.OpenFeatureClass("SHEEP_LOCATIONS");
            using (var comReleaser = new ComReleaser())
            {
                IFeatureCursor cursor = featureClass.Search(filter, false);
                comReleaser.ManageLifetime(cursor);

                var locationFeature = cursor.NextFeature();
                if (locationFeature == null) return;
                locationFeature.Shape = location;
                locationFeature.set_Value(locationFeature.Fields.FindField("ReportTime"), DateTime.Now);
                locationFeature.Store();
            }
        }

        private void UpdateTrack(int code, IPoint location, IFeatureWorkspace workspace)
        {
            var filter = new QueryFilter {WhereClause = " Code = " + code};
            var featureClass = workspace.OpenFeatureClass("SHEEP_TRACK");
            using (var comReleaser = new ComReleaser())
            {
                IFeatureCursor cursor = featureClass.Search(filter, false);
                comReleaser.ManageLifetime(cursor);

                var track = cursor.NextFeature();
                if (track == null) return;

                var line = (IPolyline)track.Shape;
                ((IPointCollection)line).AddPoint(location, ref _missing, ref _missing);
                track.Store();
            }
        }

        private void InitializeLicense()
        {
            if (!RuntimeManager.Bind(ProductCode.Engine))
            {
                throw new ApplicationException(
                    "Unable to bind to ArcGIS license Server nor to Engine. Please check your licenses.");
            }
            IAoInitialize aoInitialize = new AoInitializeClass();
            var esriLicenseStatus = aoInitialize.Initialize(esriLicenseProductCode.esriLicenseProductCodeEngineGeoDB);
            if (esriLicenseStatus == esriLicenseStatus.esriLicenseUnavailable ||
                esriLicenseStatus == esriLicenseStatus.esriLicenseNotLicensed)
            {
                throw new ApplicationException(
                    "Unable to bind to ArcGIS license Server nor to Engine. Please check your licenses.");
            }
        }
    }
}
